package cn.tedu.lucky.draw.server.service.impl;

import cn.tedu.lucky.draw.server.common.enums.DrawEnum;
import cn.tedu.lucky.draw.server.common.handler.DrawException;
import cn.tedu.lucky.draw.server.protocol.po.Activity;
import cn.tedu.lucky.draw.server.protocol.po.ActivityResult;
import cn.tedu.lucky.draw.server.protocol.po.Prize;
import cn.tedu.lucky.draw.server.protocol.po.Rule;
import cn.tedu.lucky.draw.server.protocol.query.ActivityQuery;
import cn.tedu.lucky.draw.server.repository.ActivityRepository;
import cn.tedu.lucky.draw.server.repository.ActivityResultRepository;
import cn.tedu.lucky.draw.server.service.IActivityRuleService;
import cn.tedu.lucky.draw.server.service.IActivityService;
import cn.tedu.lucky.draw.server.service.IPrizeService;
import org.json.JSONException;
import org.json.JSONObject;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.time.LocalDateTime;
import java.util.*;
import java.util.stream.Collectors;

@Service
public class ActivityServiceImpl implements IActivityService {

    @Autowired
    private ActivityRepository activityRepository;

    @Autowired
    private IActivityRuleService activityRuleService;

    @Autowired
    private ActivityResultRepository activityResultRepository;

    @Autowired
    private IPrizeService prizeService;

    private List<Activity> activities;

    @Override
    public List<Activity> findAll() {
        Integer status = Integer.valueOf(DrawEnum.ENABLE.getCode());
        List<Activity> activityList = activityRepository.findByStatus(status);
        return activityList;
    }

    @Override
    public List<Activity> findAll(ActivityQuery activityQuery) {
        if (activities == null) {
            activities = activityRepository.findAll();
        }
        String name = activityQuery.getName();
        Integer status = activityQuery.getStatus();
        return activities.stream()
                .filter(activity -> name == null || name == "" || name.equals(activity.getName()))
                .filter(activity -> status == null || status.equals(activity.getStatus()))
                .collect(Collectors.toList());
    }

    @Override
    public void save(Activity activity) {
        LocalDateTime now = LocalDateTime.now();
        activity.setCreateTime(now);
        activity.setUpdateTime(now);
        activity.setStatus(0);//待审核
        activityRepository.save(activity);
        activities = null;
    }

    @Override
    public Activity findActivityById(Long id) {
        Optional<Activity> optional = activityRepository.findById(id);
        return optional.orElse(null);
    }

    @Override
    public Prize trigger(Long activityId) throws JSONException {
        List<Rule> ruleList = activityRuleService.findAllByActivityId(activityId);
        boolean value = false;
        for (Rule rule : ruleList) {
            //如果type=1，则当前规则表示抽奖次数
            if (rule.getType()==1){
                JSONObject jsonObject = new JSONObject(rule.getContent());
                //活动规则所限制的抽奖次数
                int count = jsonObject.getInt("count");
                //获取用户ID
                Long userId = getUserId();
                //根据活动ID和用户ID获取已经参加的次数
                int row = activityResultRepository.countByActivityIdAndUserId(activityId, userId);
                //判断用户是否还可以继续参与抽奖
                if (row>=count){
                    throw new DrawException(DrawEnum.TIMES_EXHAUSTED);
                }
            }else{
                JSONObject jsonObject = new JSONObject(rule.getContent());
                value = jsonObject.getBoolean("value");
            }
        }

        //触发抽奖逻辑
        List<Prize> prizes = prizeService.findPrizeByActivityId(activityId);
        // 分配抽奖概率
        Map<Prize, Double> prizeProbabilityMap = new HashMap();

        double totalInverseValue = prizes.stream().mapToDouble(prize -> 1.0 / prize.getValue()).sum();

        // 如果需要降低概率，则所有概率值乘以一个小于1的因子
        double decreaseFactor = value ? 0.5 : 1.0;

        for (Prize prize : prizes) {
            double individualProbability = (1.0 / prize.getValue()) / totalInverseValue;
            prizeProbabilityMap.put(prize, individualProbability * decreaseFactor);
        }

        // 执行抽奖 0.8
        //第一个奖品的概率是0.3，第二个奖品的概率是0.3,第三个奖品的概率是0.1，第四个奖品概率是0.2
        double randomValue = new Random().nextDouble();
        double cumulativeProbability = 0.0;
        for (Map.Entry<Prize, Double> entry : prizeProbabilityMap.entrySet()) {
            Prize prize = entry.getKey();
            Double probability = entry.getValue();

            cumulativeProbability += probability;
            if (randomValue <= cumulativeProbability) {
                prize.setStock(prize.getStock()-1);
                prizeService.save(prize);//更新奖品库存
                saveActivityResult(activityId,prize.getId());//记录中奖信息
                return prize; // 返回中奖的奖品对象
            }
        }
        //如果没有抽中任何奖品
        Prize prize = new Prize();
        prize.setName("谢谢参与");
        prize.setImg("谢谢参与.jpg");
        prize.setId(9999999999999999L);
        saveActivityResult(activityId,prize.getId());//记录中奖信息
        return prize;
    }

    public void saveActivityResult(Long activityId, Long id) {
        ActivityResult activityResult = new ActivityResult();
        activityResult.setActivityId(activityId);
        activityResult.setPrizeId(id);
        activityResult.setUserId(getUserId());
        activityResult.setWinTime(LocalDateTime.now());
        activityResult.setStatus(Integer.valueOf(DrawEnum.NOT_RELEASED.getCode()));//未发放
        activityResultRepository.save(activityResult);
    }

    private Long getUserId() {
        return 9999L;
    }
}
